package com.bicon.botu.finance.payment.alipay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @Author: 宋旭
 * @Date: Created in 10:01 2017/7/31/031
 */
@Slf4j
public class AliPayApi {



    /**
     * App支付
     * @param model
     * @param notifyUrl
     * @return
     * @throws AlipayApiException
     */
    public static String startAppPayStr(AliPayApiConfig aliPayApiConfig,AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException{
        AlipayTradeAppPayResponse response = appPay(aliPayApiConfig,model,notifyUrl);
        return response.getBody();
    }

    /**
     * App 支付
     * https://doc.open.alipay.com/docs/doc.htm?treeId=54&articleId=106370&docType=1
     * @param aliPayApiConfig
     * @param model
     * @param notifyUrl
     * @return
     * @throws AlipayApiException
     */
    public static AlipayTradeAppPayResponse appPay(AliPayApiConfig aliPayApiConfig,AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException{
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        //这里和普通的接口调用不同，使用的是sdkExecute
        AlipayTradeAppPayResponse response = aliPayApiConfig.getAlipayClient().sdkExecute(request);
        return response;
    }

    /**
     * Wap支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dfHHR3&
     * treeId=203&articleId=105285&docType=1
     * @param aliPayApiConfig
     * @param response
     * @param model
     * @param returnUrl
     * @param notifyUrl
     * @throws AlipayApiException
     * @throws IOException
     */
    public static void wapPay(AliPayApiConfig aliPayApiConfig,HttpServletResponse response, AlipayTradeWapPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        String form = wapPayToString(aliPayApiConfig,response, model, returnUrl, notifyUrl);
        HttpServletResponse httpResponse = response;
        httpResponse.setContentType("text/html;charset=" + aliPayApiConfig.getCharset());
        httpResponse.getWriter().write(form);// 直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
    }

    /**
     * Wap支付
     * @param aliPayApiConfig
     * @param response
     * @param model
     * @param returnUrl
     * @param notifyUrl
     * @return
     * @throws AlipayApiException
     * @throws IOException
     */
    public static String wapPayToString(AliPayApiConfig aliPayApiConfig,HttpServletResponse response,AlipayTradeWapPayModel model,String returnUrl,String notifyUrl) throws AlipayApiException, IOException {
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();// 创建API对应的request
        alipayRequest.setReturnUrl(returnUrl);
        alipayRequest.setNotifyUrl(notifyUrl);// 在公共参数中设置回跳和通知地址
        alipayRequest.setBizModel(model);// 填充业务参数
        return aliPayApiConfig.getAlipayClient().pageExecute(alipayRequest).getBody(); // 调用SDK生成表单
    }

    /**
     * 条形码支付、声波支付
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7629065.0.0.XVqALk&apiId=850&docType=4
     * @param notifyUrl
     * @throws AlipayApiException
     */
    public static String tradePay(AliPayApiConfig aliPayApiConfig,AlipayTradePayModel model, String notifyUrl) throws AlipayApiException {
        AlipayTradePayResponse response = tradePayToResponse(aliPayApiConfig,model,notifyUrl);
        return response.getBody();
    }

    public static AlipayTradePayResponse tradePayToResponse(AliPayApiConfig aliPayApiConfig,AlipayTradePayModel model, String notifyUrl) throws AlipayApiException{
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        request.setBizModel(model);// 填充业务参数
        request.setNotifyUrl(notifyUrl);
        return aliPayApiConfig.getAlipayClient().execute(request); // 通过aliPayApiConfig.getAlipayClient()调用API，获得对应的response类
    }


    /**
     * * 扫码支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.i0UVZn&treeId=193&articleId=105170&docType=1#s4
     * @param aliPayApiConfig
     * @param model
     * @param notifyUrl
     * @return
     * @throws AlipayApiException
     */
    public static String tradePrecreatePay(AliPayApiConfig aliPayApiConfig,AlipayTradePrecreateModel model, String notifyUrl) throws AlipayApiException{
        AlipayTradePrecreateResponse response = tradePrecreatePayToResponse(aliPayApiConfig,model,notifyUrl);
        return response.getBody();
    }
    public static AlipayTradePrecreateResponse tradePrecreatePayToResponse(AliPayApiConfig aliPayApiConfig,AlipayTradePrecreateModel model, String notifyUrl) throws AlipayApiException{
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }

    /**
     * 单笔转账到支付宝账户
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.54Ty29&treeId=193&articleId=106236&docType=1
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static boolean transfer(AliPayApiConfig aliPayApiConfig,AlipayFundTransToaccountTransferModel model) throws AlipayApiException{
        AlipayFundTransToaccountTransferResponse response = transferToResponse(aliPayApiConfig,model);
        String result = response.getBody();
        log.info("transfer result>"+result);
        if (response.isSuccess()) {
            return true;
        } else {
            //调用查询接口查询数据
            JSONObject jsonObject = JSONObject.parseObject(result);
            String out_biz_no = jsonObject.getJSONObject("alipay_fund_trans_toaccount_transfer_response").getString("out_biz_no");
            AlipayFundTransOrderQueryModel queryModel = new AlipayFundTransOrderQueryModel();
            model.setOutBizNo(out_biz_no);
            boolean isSuccess = transferQuery(aliPayApiConfig,queryModel);
            if (isSuccess) {
                return true;
            }
        }
        return false;
    }

    public static AlipayFundTransToaccountTransferResponse transferToResponse(AliPayApiConfig aliPayApiConfig,AlipayFundTransToaccountTransferModel model) throws AlipayApiException{
        AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }

    /**
     * 转账查询接口
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static boolean transferQuery(AliPayApiConfig aliPayApiConfig,AlipayFundTransOrderQueryModel model) throws AlipayApiException{
        AlipayFundTransOrderQueryResponse response = transferQueryToResponse(aliPayApiConfig,model);
        log.info("transferQuery result>"+response.getBody());
        if(response.isSuccess()){
            return true;
        }
        return false;
    }
    public static AlipayFundTransOrderQueryResponse transferQueryToResponse(AliPayApiConfig aliPayApiConfig,AlipayFundTransOrderQueryModel model) throws AlipayApiException{
        AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }

    /**
     * 交易查询接口
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static boolean isTradeQuery(AliPayApiConfig aliPayApiConfig,AlipayTradeQueryModel model) throws AlipayApiException{
        AlipayTradeQueryResponse response = tradeQuery(aliPayApiConfig,model);
        if(response.isSuccess()){
            return true;
        }
        return false;
    }

    public static AlipayTradeQueryResponse  tradeQuery(AliPayApiConfig aliPayApiConfig,AlipayTradeQueryModel model) throws AlipayApiException{
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }


    /**
     * 交易撤销接口
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7395905.0.0.XInh6e&docType=4&apiId=866
     * @param bizContent
     * @return
     * @throws AlipayApiException
     */
    public static boolean isTradeCancel(AliPayApiConfig aliPayApiConfig,AlipayTradeCancelModel model) throws AlipayApiException{
        AlipayTradeCancelResponse response = tradeCancel(aliPayApiConfig,model);
        if(response.isSuccess()){
            return true;
        }
        return false;
    }

    public static AlipayTradeCancelResponse tradeCancel(AliPayApiConfig aliPayApiConfig,AlipayTradeCancelModel model) throws AlipayApiException{
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        request.setBizModel(model);
        AlipayTradeCancelResponse response = aliPayApiConfig.getAlipayClient().execute(request);
        return response;
    }
    /**
     * 关闭订单
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7629065.0.0.21yRUe&apiId=1058&docType=4
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static boolean isTradeClose(AliPayApiConfig aliPayApiConfig,AlipayTradeCloseModel model) throws AlipayApiException{
        AlipayTradeCloseResponse response = tradeClose(aliPayApiConfig,model);
        if(response.isSuccess()){
            return true;
        }
        return false;
    }

    public static AlipayTradeCloseResponse tradeClose(AliPayApiConfig aliPayApiConfig,AlipayTradeCloseModel model) throws AlipayApiException{
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);

    }
    /**
     * 统一收单交易创建接口
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7629065.0.0.21yRUe&apiId=1046&docType=4
     * @param model
     * @param notifyUrl
     * @return
     * @throws AlipayApiException
     */
    public static AlipayTradeCreateResponse tradeCreate(AliPayApiConfig aliPayApiConfig,AlipayTradeCreateModel model, String notifyUrl) throws AlipayApiException{
        AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }


    /**
     * 退款
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7395905.0.0.SAyEeI&docType=4&apiId=759
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static String tradeRefund(AliPayApiConfig aliPayApiConfig,AlipayTradeRefundModel model) throws AlipayApiException{
        AlipayTradeRefundResponse response = tradeRefundToResponse(aliPayApiConfig,model);
        return response.getBody();
    }

    public static AlipayTradeRefundResponse tradeRefundToResponse(AliPayApiConfig aliPayApiConfig, AlipayTradeRefundModel model) throws AlipayApiException{
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }

    /**
     * 退款查询
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7629065.0.0.KQeTSa&apiId=1049&docType=4
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static String tradeRefundQuery(AliPayApiConfig aliPayApiConfig,AlipayTradeFastpayRefundQueryModel model) throws AlipayApiException{
        AlipayTradeFastpayRefundQueryResponse response = tradeRefundQueryToResponse(aliPayApiConfig,model);
        return response.getBody();
    }

    public static AlipayTradeFastpayRefundQueryResponse tradeRefundQueryToResponse(AliPayApiConfig aliPayApiConfig,AlipayTradeFastpayRefundQueryModel model) throws AlipayApiException{
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }


    /**
     * 查询对账单下载地址
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static String billDownloadurlQuery(AliPayApiConfig aliPayApiConfig,AlipayDataDataserviceBillDownloadurlQueryModel model) throws AlipayApiException{
        AlipayDataDataserviceBillDownloadurlQueryResponse response =  billDownloadurlQueryToResponse(aliPayApiConfig,model);
        return response.getBillDownloadUrl();
    }

    public static AlipayDataDataserviceBillDownloadurlQueryResponse  billDownloadurlQueryToResponse (AliPayApiConfig aliPayApiConfig,AlipayDataDataserviceBillDownloadurlQueryModel model) throws AlipayApiException{
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }


    /**
     * 交易结算接口
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7395905.0.0.nl0RS3&docType=4&apiId=1147
     * @param aliPayApiConfig
     * @param model
     * @return
     * @throws AlipayApiException
     */
    public static boolean isTradeOrderSettle(AliPayApiConfig aliPayApiConfig,AlipayTradeOrderSettleModel model) throws AlipayApiException{
        AlipayTradeOrderSettleResponse  response  = tradeOrderSettle(aliPayApiConfig,model);
        if(response.isSuccess()){
            return true;
        }
        return false;
    }

    public static AlipayTradeOrderSettleResponse tradeOrderSettle(AliPayApiConfig aliPayApiConfig,AlipayTradeOrderSettleModel model) throws AlipayApiException{
        AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
        request.setBizModel(model);
        return aliPayApiConfig.getAlipayClient().execute(request);
    }

    /**
     * 电脑网站支付(PC支付)
     * @param model
     * @param notifyUrl
     * @param returnUrl
     * @return
     * @throws AlipayApiException
     * @throws IOException
     */
    public static void tradePage(AliPayApiConfig aliPayApiConfig,HttpServletResponse httpResponse, AlipayTradePayModel model, String notifyUrl, String returnUrl) throws AlipayApiException, IOException{
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        request.setReturnUrl(returnUrl);
        String form  = aliPayApiConfig.getAlipayClient().pageExecute(request).getBody();//调用SDK生成表单
        httpResponse.setContentType("text/html;charset=" + aliPayApiConfig.getCharset());
        httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }


    /**
     * 将异步通知的参数转化为Map
     * @param request
     * @return
     */
    public static Map<String, String> toMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        return params;
    }
}
